home *** CD-ROM | disk | FTP | other *** search
- ;Listing 4 High Resolution Clock
- ;(C) Copyright 1986 Ken Berry.
- ;All rights reserved.
- ;Copies may be made for non-commercial, private use only.
- ;
-
- include tele.mac ; system defintions (listing 2)
-
- extrn t_syxtm:word ; system execution time accumulator
- extrn sys_dgrp:word ; data segment storage
- extrn sys_stat:word ; original register block
-
- public t__tick ; system tick interrupt service
- public t_astrm ; application task termination flag
- public tmr_dspl ; physical display pointer
- public tmr_dvsr ; timer period
- public tmr_ilck ; tick service reentrant interlock
- public tmr_sync ; synchronization function address
- public tmr_tkct ; tick clock
- public tmr_xtm ; tick service execution time
- public tmr__clr ; reset time base generation
- public tmr__int ; timer initialization function
- public tmr__rst ; timer termination function
- public tmr__sts ; read timer status
- public tmr__tmr ; restart hardware timer
- public t_rdclk ; read high resolution clock
- public t_rtactg ; psuedo time accumulator pointer
- public t_rtmark ; mark execution interval
- public t__rdclk ; read real time clock
- public td_ref ; clock update tick reference count
- public td_tct ; clock tick timer
- public td__set ; set time of day clock
- public td__upd ; update time of day clock
- public w__cdspl ; physical display update function
- public w__sync ; physical display synchronization
-
- RLCINT equ 80h ; relocated alternate time base interrupt
- TMRINT equ 8 ; hardware timer interrupt
- TMRPRT equ 40h ; timer (8253) port
- TMRPRD equ 19912 ; timer period (60 Hz rate)
- ;TMRPRD equ 9956 ; timer period (120 Hz rate)
- INTPRT equ 20h ; interrupt controller (8259) port
- TMRMSK equ 01h ; hardware timer interrupt mask
- INTEOI equ 20h ; interrupt termination value
- DSPCT equ 1 ; 60 Hz interrupt rate
- ;DSPCT equ 2 ; 120 Hz interrupt rate
- IDV0 equ 3 ; tmr_idv0 divisor
- ISKP0 equ 776 ; tmr_ict correction value
- ISKP1 equ 11 ; tmr_idv1 correction value
- ISKP2 equ 38 ; tmr_idv2 correction value
-
- dseg
-
- tmr_tkct dw 0 ; interrupt counter
- tmr_dct db 0 ; display counter
- tmr_ict dw 0 ; tick clock (for time base generation)
- tmr_dvsr dw TMRPRD ; 1/2 timer period
- t_astrm db 0FFh ; application task termination flag
- tmrflg db 0FFh ; system state flag (t__tick)
- tmr_ilck db 0 ; tick service reentrant interlock
- tmr_idv0 db 0 ; clock time base generator
- tmr_idv1 db 0 ; primary alternate time base generator
- tmr_idv2 db 0 ; secondary alternate time base generator
- tmr_dspl dw 0 ; console display w_pwdw pointer
- t_rtactg dw 0 ; psuedo time accumulator pointer
- t_rtrfct dw 0 ; real time reference count
- t_rttick dw 0 ; tick clock phase
- tmr_xtm dw 3 dup (0) ; tick service psuedo time accumulator
- tmrpxtm dw 0 ; prior psuedo time accumulator pointer
- tmr_sync dw offset pgroup:w__sync ; synchronization function pointer
- td_ref dw 0 ; clock update tick reference count
- td_tct dw 0 ; clock tick timer
-
- endds
-
- pseg
-
- ;t__tick system tick service
- ;
- ;t__tick\\
- ;
- ;Control only comes here in response to an interrupt from the system clock.
- ;This function serves three purposes. It maintains the system clock, which
- ;provides the current date and time for both system and application uses. It
- ;also performs an update of the first physical display. And finally it
- ;terminates the execution interval for the current application task.
- ;
-
- t__tick proc far
-
- ; reentrant lockout
-
- assume ss:nothing,ds:nothing,es:nothing
- sti ; interrupts on
- push ds ; protect ds
- push ax ; protect ax
- mov ax,dgroup ; establish data addressability
- mov ds,ax
- assume ds:dgroup
- mov al,INTEOI ; terminate interrupt
- out INTPRT,al
- ilck al,tmr_ilck ; test for not reentrant call
- or al,al
- jz tick
- pop ax ; restore ax
- pop ds ; restore ds
- iret ; return from interrupt
-
- ; system interlock
-
- tick: mov t_astrm,0FFh ; terminate application task
- sys_entr tmrflg ; enter system state
-
- ; set machine environment
-
- sys_sctx ; save processor context
- push bp ; protect bp
- mov bp,sp ; mark stack location
- lea ax,tmr_xtm ; accumulate psuedo time
- push ax
- call t_rtmark
- mov sp,bp
- mov tmrpxtm,ax ; store prior pointer
-
- ; real time system processing
-
- inc tmr_dct ; remove display harmonics
- mov al,DSPCT
- xor al,tmr_dct
- jnz tick4
- mov tmr_dct,al
- push tmr_dspl ; display physical window
- call w__cdspl
- mov sp,bp ; restore stack pointer
- inc tmr_ict ; increment interrupt counter
- inc tmr_tkct ; increment tick clock
-
- ; time base generation
-
- mov ax,ISKP0 ; long term time base correction
- xor ax,tmr_ict
- jnz tick1
- mov tmr_ict,ax
- call tick5 ; update system tick clock
- tick1: inc tmr_idv0 ; generate clock time base
- mov al,IDV0
- xor al,tmr_idv0
- jnz tick3
- mov tmr_idv0,al
- call tick5 ; update system tick clock
- inc tmr_idv1 ; primary alternate time base correction
- mov al,ISKP1
- xor al,tmr_idv1
- jnz tick2
- mov tmr_idv1,al
- int RLCINT ; update alternate time base
- inc tmr_idv2 ; secondary alternate time base correction
- mov al,ISKP2
- xor al,tmr_idv2
- jnz tick2
- mov tmr_idv2,al
- int RLCINT ; update alternate time base
- tick2: int RLCINT ; update alternate time base
-
- ; terminate interrupt service
-
- tick3: push tmrpxtm ; restore original psuedo time accumulator
- call t_rtmark
- mov sp,bp
- pop bp ; restore bp
- test tmrflg,0FFh ; test for interrupted system task
- jnz tick4
- xor ax,ax ; terminate task
- mov tmr_ilck,al ; enable reentrance
- retn ; near return to system task management
-
- tick4: sys__rctx ; restore processor context
- cli ; interrupts off
- mov tmr_ilck,0 ; enable reentrance
- pop ds ; restore ds
- iret ; return to interrupted task
-
- ; update system tick counter
-
- tick5: mov ax,td_tct ; test for no overflow
- inc ax
- cmp ax,td_ref
- jne tick6
- call td__upd ; update clock
- xor ax,ax ; reset tick counter
- mov td_ref,ax
- mov td_tct,ax
- tick6: inc td_tct ; increment tick counter
- retn ; return
-
- t__tick endp
-
- ;tmr__int initialize timer
- ;
- ;tmr__int()
- ;
- ;All data areas necessary for clock maintenance are initialized. The hardware
- ;timer is programmed for the appropriate rate and its interrupt vector is made
- ;to point to sys_tmr. The original vector is relocated and will be used by
- ;sys_tmr as the alternate time base.
- ;
-
- tmr__int proc near
- call tmr__dsi ; diable interrupts
- mov ax,dgroup ; set data segment
- mov sys_dgrp,ax
- mov ax,cs ; set code segment
- lea si,sys_stat
- mov [si].rcs,ax
- cli ; interrupts off
- mov tmr_ilck,0FFh ; lockout t__tick
- mov bx,tmr_sync ; test for no synchronization function
- test bx,bx
- jz int0
- lea bx,tmr_sync ; synchronize timer interrupt
- call [bx]
- jmp short int1 ; continue
- int0: call tmr__tmr ; start timer
- int1: call t_rdclk ; set real time clock phase
- mov t_rttick,ax
- mov t_rtrfct,ax ; set reference count
- mov t_rtactg,offset dgroup:t_syxtm ; initialize time accumulator
- call td__set ; set current time
- sti ; interrupts on
- xor ax,ax ; form 0
- push ds ; protect ds
- mov ds,ax ; relocate original interrupt vector
- mov di,ax
- cli
- mov ax,[di+4*TMRINT]
- mov [di+4*RLCINT],ax
- mov ax,[di+4*TMRINT+2]
- mov [di+4*RLCINT+2],ax
- mov ax,offset pgroup:t__tick ; set interrupt service
- mov [di+4*TMRINT],ax
- mov ax,cs
- mov [di+4*TMRINT+2],ax
- sti ; interrupts on
- pop ds ; restore ds
- call tmr__eni ; enable interrupts
- ret ; return
- tmr__int endp
-
- ;
- ;tmr__clr reset time base generation
- ;
- ;tmr__clr()
- ;
- ;The time base adjustment variables are reset. This function is to be called by
- ;td__set when the time of day is initially set from a continuous clock. Nothing
- ;is returned.
- ;
-
- tmr__clr proc near
- xor ax,ax ; zero time base generation variables
- mov tmr_idv0,al
- mov tmr_idv1,al
- mov tmr_idv2,al
- ret ; return
- tmr__clr endp
-
-
- ;tmr__rst reset timer
- ;
- ;tmr__rst()
- ;
- ;The original interrupt service routine is restored and the hardware clock is
- ;reprogrammed. However, the original hardware values are not available in this
- ;edition. Therefore the original system state cannot always be restored.
- ;
-
- tmr__rst proc near
- mov tmr_ilck,0FFh ; lock out interrupt service
- push ds ; protect ds
- xor ax,ax ; restore original interrupt vector
- mov ds,ax
- mov di,ax
- call tmr__dsi ; disable timer interrupt
- cli ; interrupts off
- mov ax,[di+4*RLCINT]
- mov [di+4*TMRINT],ax
- mov ax,[di+4*RLCINT+2]
- mov [di+4*TMRINT+2],ax
- pop ds ; restore ds
- xor bx,bx ; restart hardware timer
- call tmr__str
- sti ; interrupts on
- call tmr__eni ; enable timer interrupt
- ret ; return
- tmr__rst endp
-
- ;tmr__tmr restart hardware timer
- ;
- ;tmr__tmr\\
- ;
- ;Channel 0 of an 8253 timer is initialized to mode 3. The count in bx is then
- ;programmed.
- ;
-
- tmr__tmr proc near ; restart timer
- mov bx,tmr_dvsr ; set tele system tick period
- tmr__str proc near ; set timer period
- mov al,20 ; reset 8253 (mode 0, count >= 8,192)
- out TMRPRT+3,al ; [> 6.8 msec]
- iowait
- out TMRPRT,al
- mov al,36h ; initialize 8253 (mode 3, both bytes)
- iowait
- out TMRPRT+3,al
- mov al,bl
- iowait
- out TMRPRT,al
- mov al,bh
- iowait
- out TMRPRT,al
- ret ; return
- tmr__str endp
- tmr__tmr endp
-
- ;tmr__sts read timer status
- ;
- ;tmr__sts()
- ;
- ;The returned value is the current count in the timer.
- ;
-
- tmr__sts proc near ; read timer status
- mov al,00h ; set read mode
- out TMRPRT+3,al
- nop ; allow timer chip to recover
- in al,TMRPRT ; read count
- mov ah,al
- in al,TMRPRT
- xchg ah,al
- ret ; return
- tmr__sts endp
-
- ;
- ;tmr__dsi disable interrupt
- ;
- ;tmr__dsi()
- ;
- ;The timer interrupt is disabled at the 8259 interrupt controller.
- ;
-
- tmr__dsi proc near
- cli ; interrupts off
- in al,INTPRT+1 ; disable timer interrupt
- or al,TMRMSK
- iowait
- out INTPRT+1,al
- sti ; interrupts on
- ret ; return
- tmr__dsi endp
-
- ;tmr__eni enable interrupt
- ;
- ;tmr__eni()
- ;
- ;The timer interrupt is enabled at the 8259 interrupt controller.
- ;
-
- tmr__eni proc near
- cli ; interrupts off
- in al,INTPRT+1; ; enable timer interrupt
- and al,not TMRMSK
- iowait
- out INTPRT+1,al
- sti ; interrupts on
- ret ; return
- tmr__eni endp
-
- ;
- ;t_rdclk read real time clock
- ;
- ;t_rdclk()
- ;
- ;The current value of the real time clock is read and returned.
- ;
-
- DMAREG equ 0 ; refresh address DMA register
-
- t_rdclk proc near
- rdclk0: mov dx,DMAREG ; set DMA register address
- call t__rdclk ; read time
- mov bx,ax ; store time
- call t__rdclk ; read time again
- cmp ah,bh ; test for interruption
- jne rdclk0
- ret ; return
- t_rdclk endp
-
- t__rdclk proc near
- cli ; interrupts off
- in al,dx ; read time
- mov ah,al
- iowait
- in al,dx
- xchg al,ah
- sti ; interrupts on
- ret ; return
- t__rdclk endp
-
- ;t_rtmark mark execution interval
- ;
- ;t_rtmark(np)
- ;pointer *np;
- ;
- ;The number of refreshes since the last call to t_rtmark is accumulated. Then
- ;the reference count is reset. np points to the area that will accumulate the
- ;number of refreshes to the next call. The returned value is the original
- ;accumulator pointer.
- ;
-
- t_rtmark proc near
- push bp ; protect bp
- mov bp,sp ; establish parameter addressability
- call tmr__dsi ; disable timer interrupt
- call t_rdclk ; read real time clock
- mov bx,ax ; protect current count
- xchg bx,t_rtrfct ; update reference count
- sub ax,bx ; compute execution interval
- jnc mark1 ; test for no overflow
- neg ax ; adjust count
- mark1: mov bx,t_rtactg ; accumulate execution time
- add ax,[bx]
- mov [bx],ax
- jnc markxit
- add word ptr [bx+2],1
- jnc markxit
- inc word ptr [bx+4]
- markxit: mov ax,bx ; return orginal pointer
- mov bx,[bp].t_np0 ; set new accumulator pointer
- mov t_rtactg,bx
- call tmr__eni ; enable timer interrupt
- pop bp ; restore bp
- ret ; return
- t_rtmark endp
-
- ;w__cdspl display physical buffer
- ;
- ;w__cdspl(pw)
- ;struct w_phys *pw;
- ;
- ;Physical window pw is displayed. This function is called by the system tick
- ;clock interrupt service function. Nothing is returned.
- ;
-
- w__cdspl proc near
- ret ; return
- w__cdspl endp
-
- ;
- ;w__sync synchronize interrupt to display
- ;
- ;w__sync()
- ;
- ;The system tick clock timer is adjusted so that w__dsply executes just prior
- ;to the vertical blanking interval. Nothing is returned.
- ;
-
- w__sync proc near
- call tmr__tmr ; start timer
- w__sync endp
-
- ;
- ;td__set set time of day clock
- ;
- ;td__set()
- ;
- ;The clock is set to the current time. Nothing is returned.
- ;
-
- td__set proc near
- ret ; return
- td__set endp
-
- ;
- ;td__upd update clock
- ;
- ;td__upd()
- ;
- ;The clock is updated based on the number of ticks since it was last updated.
- ;The normal return (ax) is _F. _E is returned if the call was locked out.
- ;
-
- td__upd proc near
- ret ; return
- td__upd endp
-
- endps
-
- end